﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Web;
using System.Web.Caching;

namespace Als.Common.Net
{
    public static class CacheHelper
    {
        /// <summary>
        /// cache
        /// </summary>
        private static volatile Cache _cache = HttpRuntime.Cache;

        /// <summary>
        /// timeout 600秒
        /// </summary>
        private const int TimeOut = 600 * 2;

        ///// <summary>
        ///// lock object
        ///// </summary>
        //private static object lockobj = new object();

        /// <summary>
        /// 添加缓存 (绝对有效期)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        public static void Set(string cacheKey, object cacheValue)
        {
            Set(cacheKey, cacheValue, TimeOut);
        }

        /// <summary>
        /// 添加缓存 (绝对有效期)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        /// <Param name="timeout">绝对有效期（单位: 秒）</Param>
        public static void Set(string cacheKey, object cacheValue, int timeout)
        {

            if (string.IsNullOrEmpty(cacheKey))
            {
                return;
            }
            if (null == cacheValue)
            {
                Remove(cacheKey);
                return;
            }
            var callBack = new CacheItemRemovedCallback(OnRemove);
            if (timeout <= 0)
            {
                _cache.Insert(cacheKey, cacheValue, null, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.High, callBack);
            }
            else
            {
                _cache.Insert(cacheKey, cacheValue, null, DateTime.Now.AddSeconds(timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, callBack);
            }
        }

        /// <summary>
        /// 添加缓存 (相对有效期)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        public static void AddCacheSlidingExpiration(string cacheKey, object cacheValue)
        {
            AddCacheSlidingExpiration(cacheKey, cacheValue, TimeOut);
        }

        /// <summary>
        /// 添加缓存 (相对有效期)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        /// <Param name="timeout">相对过期时间 (单位: 秒)</Param>
        public static void AddCacheSlidingExpiration(string cacheKey, object cacheValue, int timeout)
        {
            if (string.IsNullOrEmpty(cacheKey))
            {
                return;
            }
            if (null == cacheValue)
            {
                Remove(cacheKey);
                return;
            }
            var callBack = new CacheItemRemovedCallback(OnRemove);
            if (timeout <= 0)
            {
                _cache.Insert(cacheKey, cacheValue, null, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.High, callBack);
            }
            else
            {
                _cache.Insert(cacheKey, cacheValue, null, Cache.NoAbsoluteExpiration, TimeSpan.FromSeconds(timeout), CacheItemPriority.High, callBack);
            }
        }

        /// <summary>
        /// 添加缓存 (文件依赖)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        /// <Param name="filenames">缓存依赖的文件或目录</Param>
        public static void AddCacheFilesDependency(string cacheKey, object cacheValue, params string[] filenames)
        {
            var dep = new CacheDependency(filenames, DateTime.Now);
            AddCacheDependency(cacheKey, cacheValue, TimeOut, dep);
        }

        /// <summary>
        /// 添加缓存 (文件依赖)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        /// <Param name="timeout">绝对过期时间 （单位：秒）</Param>
        /// <Param name="dep">缓存依赖</Param>
        public static void AddCacheDependency(string cacheKey, object cacheValue, int timeout, CacheDependency dep)
        {
            if (string.IsNullOrEmpty(cacheKey))
            {
                return;
            }
            if (null == cacheValue)
            {
                Remove(cacheKey);
                return;
            }
            var callBack = new CacheItemRemovedCallback(OnRemove);
            if (timeout <= 0)
            {
                _cache.Insert(cacheKey, cacheValue, dep, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.High, callBack);
            }
            else
            {
                _cache.Insert(cacheKey, cacheValue, dep, DateTime.Now.AddSeconds(timeout), Cache.NoSlidingExpiration, CacheItemPriority.High, callBack);
            }
        }


        /// <summary>
        /// 添加缓存 (一组键值依赖)
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        /// <Param name="cacheValue">缓存内容</Param>
        /// <Param name="cachekeys">一组缓存键，此改变缓存也失效</Param>
        public static void AddCacheKeysDependency(string cacheKey, object cacheValue, string[] cachekeys)
        {
            var dep = new CacheDependency(null, cachekeys, DateTime.Now);
            AddCacheDependency(cacheKey, cacheValue, TimeOut, dep);
        }

        /// <summary>
        /// 缓存删除的委托实例
        /// </summary>
        /// <Param name="key"></Param>
        /// <Param name="val"></Param>
        /// <Param name="reason"></Param>
        private static void OnRemove(string key, object val, CacheItemRemovedReason reason)
        {
            switch (reason)
            {
                case CacheItemRemovedReason.DependencyChanged:
                    break;
                case CacheItemRemovedReason.Expired:
                    break;
                case CacheItemRemovedReason.Removed:
                    break;
                case CacheItemRemovedReason.Underused:
                    break;
                default: break;
            }
        }

        /// <summary>
        /// 删除缓存
        /// </summary>
        /// <Param name="cacheKey">缓存键值</Param>
        public static void Remove(string cacheKey)
        {
            if (!string.IsNullOrEmpty(cacheKey))
                _cache.Remove(cacheKey);
        }

        /// <summary>
        /// 获取缓存。若没有设置过传入的cacheKey，则返回null
        /// </summary>
        /// <Param name="cacheKey">对象的关键字</Param>
        /// <returns></returns>
        public static object Get(string cacheKey)
        {
            return string.IsNullOrEmpty(cacheKey) ? null : _cache.Get(cacheKey);
        }

        /// <summary>
        /// 获取缓存数量
        /// </summary>
        /// <returns></returns>
        public static int GetCount()
        {
            return _cache.Count;
        }

        /// <summary>
        /// 返回缓存键值列表
        /// </summary>
        /// <returns></returns>
        public static List<string> GetKeys()
        {
            var cacheKeys = new List<string>();
            var cacheEnum = _cache.GetEnumerator();
            while (cacheEnum.MoveNext())
            {
                if (cacheEnum.Key != null) cacheKeys.Add(cacheEnum.Key.ToString());
            }
            return cacheKeys;
        }

        /// <summary>
        /// 清空所有缓存
        /// </summary>
        public static void Clear()
        {
            var cacheKeys = GetKeys();
            foreach (var cacheKey in cacheKeys)
            {
                Remove(cacheKey);
            }
        }

    }
}
